use async_broadcast::{broadcast, Receiver, Sender};
use dashmap::DashMap;
use futures::Stream;
use once_cell::sync::Lazy;

pub struct File {
    total: usize,
    tx: Sender<usize>,
    rx: Receiver<usize>,
}

static FILES: Lazy<DashMap<String, File>> = Lazy::new(DashMap::new);

pub async fn add_chunk(filename: &str, len: usize) {
    println!("[{filename}]\tadding {len}");
    let mut entry = FILES.entry(filename.to_string()).or_insert_with(|| {
        println!("[{filename}]\tinserting channel");
        let (tx, rx) = broadcast(128);
        File { total: 0, tx, rx }
    });
    entry.total += len;
    let new_total = entry.total;

    // we're about to do an async broadcast, so we don't want to hold a lock across it
    let tx = entry.tx.clone();
    drop(entry);

    // now we send the message and don't have to worry about it
    tx.broadcast(new_total)
        .await
        .expect("couldn't send a message over channel");
}

pub fn for_file(filename: &str) -> impl Stream<Item = usize> {
    let entry = FILES.entry(filename.to_string()).or_insert_with(|| {
        println!("[{filename}]\tinserting channel");
        let (tx, rx) = broadcast(128);
        File { total: 0, tx, rx }
    });
    entry.rx.clone()
}
